//! 获取接口凭证
use reqwest::Client;
use serde::{Deserialize, Serialize};

use crate::common::Response;

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TokenParams {
    appid: String,
    secret: String,
    grant_type: String,
}

impl TokenParams {
    pub fn new<T>(appid: T, secret: T) -> Self
    where
        T: AsRef<str>,
    {
        Self {
            appid: appid.as_ref().to_owned(),
            secret: secret.as_ref().to_owned(),
            grant_type: "client_credential".to_string(),
        }
    }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AccessToken {
    pub access_token: String,
    pub expires_in: u16,
}

/// 获取接口凭证
pub async fn get_token(params: &TokenParams) -> Result<TokenResult, reqwest::Error> {
    let url = "https://api.weixin.qq.com/cgi-bin/token";
    let client = Client::new();
    client
        .get(url)
        .query(params)
        .send()
        .await?
        .json::<TokenResult>()
        .await
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct StableTokenParams {
    appid: String,
    secret: String,
    grant_type: String,
    forch_fresh: bool,
}

impl StableTokenParams {
    /// 创建一个不强制刷新的StableToken
    pub fn new<T>(appid: T, secret: T) -> Self
    where
        T: AsRef<str>,
    {
        Self {
            appid: appid.as_ref().to_owned(),
            secret: secret.as_ref().to_owned(),
            grant_type: "client_credential".to_owned(),
            forch_fresh: false,
        }
    }

    /// 创建一个强制刷新的StableToken
    pub fn fresh<T>(appid: T, secret: T) -> Self
    where
        T: AsRef<str>,
    {
        Self {
            appid: appid.as_ref().to_owned(),
            secret: secret.as_ref().to_owned(),
            grant_type: "client_credential".to_owned(),
            forch_fresh: true,
        }
    }
}

impl From<TokenParams> for StableTokenParams {
    fn from(value: TokenParams) -> Self {
        Self {
            appid: value.appid,
            secret: value.secret,
            grant_type: value.grant_type,
            forch_fresh: false,
        }
    }
}

type TokenResult = Response<AccessToken>;

/// 获取稳定接口凭证
pub async fn get_stable_token<'a, T>(params: &'a T) -> Result<TokenResult, reqwest::Error>
where
    &'a T: Into<&'a StableTokenParams>,
{
    let url = "https://api.weixin.qq.com/cgi-bin/stable_token";
    let client = Client::new();
    let params = params.into();
    client
        .post(url)
        .json(&params)
        .send()
        .await?
        .json::<TokenResult>()
        .await
}
